#ifndef LOG_H
#define LOG_H

#include "pch.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <memory>

#ifndef __FILENAME__
#define __FILENAME__ __FILE__
#endif

#define LOG(level)                                              \
    if (level > PROJECT_NAME::Log::GetInstance().GetLogLevel()) \
        ;                                                       \
    else                                                        \
        PROJECT_NAME::Log::GetInstance().GetStream() << "[" << __FILENAME__ << ":" << std::dec << __LINE__ << "]"

#define LOG_CPU                                                                          \
    if (PROJECT_NAME::Level::CpuTrace != PROJECT_NAME::Log::GetInstance().GetLogLevel()) \
        ;                                                                                \
    else                                                                                 \
        PROJECT_NAME::Log::GetInstance().GetCpuTraceStream()

PNE_NAMESPACE_BEGIN
enum class Level
{
    None,
    Error,
    Info,
    InfoVerbose,
    CpuTrace
};

struct Log
{
    ~Log();
    void SetLogStream(std::ostream &stream);
    void SetCpuTraceStream(std::ostream &stream);
    Log &SetLevel(Level level);
    Level GetLogLevel();

    std::ostream &GetStream();
    std::ostream &GetCpuTraceStream();

    static Log &GetInstance();

private:
    Level m_logLevel;
    std::ostream *m_logStream;
    std::ostream *m_cpuTrace;
}; // Log

// REF LINKS: https://wordaligned.org/articles/cpp-streambufs#toctee-streams
struct TeeBuf : public std::streambuf
{
    TeeBuf(std::streambuf *sb1, std::streambuf *sb2);

private:
    // this tee buffer has no buffer, so every character "overflows"
    // and can be put directory into the teed buffers
    virtual int Overflow(int c);
    // Sync both teed buffer
    virtual int Sync();

private:
    std::streambuf *m_sb1;
    std::streambuf *m_sb2;
}; // TeeBuf

struct TeeStream : public std::ostream
{
    TeeStream(std::ostream &o1, std::ostream &o2);

private:
    TeeBuf m_tbuf;
};

PNE_NAMESPACE_END // namespace

#endif // LOG_H
       // DONE